﻿@page "/custom-filtering"

@using System.Dynamic;
@using Telerik.DataSource

@inject EmployeeService EmployeeService

When using custom filtering (either through <a href="https://docs.telerik.com/blazor-ui/components/grid/templates/filter" target="_blank">filter templates</a>, or by adding some custom logic to the <a href="https://docs.telerik.com/blazor-ui/components/grid/manual-operations" target="_blank"><code>OnRead event</code></a>), you may sometimes need to add a new <code>FilterDescriptor</code> based on your business logic. When adding custom filters, you must always set their <code>MemberType</code> to match the field they will filter. This applies to all cases in the grid, and with expando objects this type must also be set on the column itself.

<TelerikGrid Data="@GridData"
             Pageable="true"
             Sortable="true"
             FilterMode="@GridFilterMode.FilterRow">
    <GridColumns>
        @*Field Type is mandatory when you are binding to ExpandoObject or Dictionary*@
        <GridColumn Field="EmployeeId" FieldType="@typeof(int)" Width="400px">
            <FilterCellTemplate>
                @{
                    // we store a reference to the filter context to use in the business logic
                    // you can also use it inline in the template, like with the Clear button below
                    theFilterContext = context;
                }

                <label for="min">Min:&nbsp;</label>
                <TelerikNumericTextBox Id="min"
                                       @bind-Value="@MinValue"
                                       OnChange="@SetupFilterRule">
                </TelerikNumericTextBox>
                <label for="min">Max:&nbsp;</label>
                <TelerikNumericTextBox Id="max"
                                       @bind-Value="@MaxValue"
                                       OnChange="@SetupFilterRule">
                </TelerikNumericTextBox>
                <TelerikButton ButtonType="ButtonType.Button"
                               Class="k-clear-button-visible ml-2"
                               Icon="filter-clear"
                               Enabled="@( MinValue != null || MaxValue != null )"
                               OnClick="@(async () =>
                                          {
                                              MinValue = MaxValue = null;

                                              // clear filter through the method the context provides
                                              await context.ClearFilterAsync();
                                          })">
                </TelerikButton>
            </FilterCellTemplate>
        </GridColumn>
        <GridColumn Field="FirstName" FieldType="@typeof(string)"></GridColumn>
        <GridColumn Field="IsActive" FieldType="@typeof(bool)"></GridColumn>
        <GridColumn Field="HireDate" FieldType="@typeof(DateTime)"></GridColumn>
    </GridColumns>
</TelerikGrid>

@code {
    public List<ExpandoObject> GridData { get; set; }


    FilterCellTemplateContext theFilterContext { get; set; }
    public int? MinValue { get; set; }
    public int? MaxValue { get; set; }

    async Task SetupFilterRule()
    {
        // this first filter comes from the grid (its filter row mode provides 1) and its type is correct
        FilterDescriptor filter1 = theFilterContext.FilterDescriptor.FilterDescriptors[0] as FilterDescriptor;
        filter1.Value = MinValue == null ? int.MinValue : MinValue;
        filter1.Operator = FilterOperator.IsGreaterThan;

        // when you create a custom filter you must set its type to the correct type for the field in the expando
        int? filter2Val = MaxValue == null ? int.MaxValue : MaxValue;
        FilterDescriptor filter2 = new FilterDescriptor("EmployeeId", FilterOperator.IsLessThan, filter2Val);
        filter2.MemberType = typeof(int);

        if (theFilterContext.FilterDescriptor.FilterDescriptors.Count > 1)
        {
            theFilterContext.FilterDescriptor.FilterDescriptors[1] = filter2;
        }
        else
        {
            theFilterContext.FilterDescriptor.FilterDescriptors.Add(filter2);
        }

        theFilterContext.FilterDescriptor.LogicalOperator = FilterCompositionLogicalOperator.And;

        await theFilterContext.FilterAsync();
    }

    protected override async Task OnInitializedAsync()
    {
        GridData = await EmployeeService.GetEmployeesAsync();
    }
}